home *** CD-ROM | disk | FTP | other *** search
/ ADA Programming Guide / ADA Programming Guide.iso / ada_gwu / adamrg.c < prev    next >
C/C++ Source or Header  |  1996-01-30  |  15KB  |  684 lines

  1. /*
  2.  * Copyright (C) 1985-1992  New York University
  3.  * 
  4.  * This file is part of the Ada/Ed-C system.  See the Ada/Ed README file for
  5.  * warranty (none) and distribution info and also the GNU General Public
  6.  * License for more details.
  7.  
  8.  */
  9.  
  10. /* adamrg - merge error and ada source files to make listing */
  11.  
  12. #include "config.h"
  13. #include <stdlib.h>
  14. #include <stdio.h>
  15. #include <ctype.h>
  16. #include <malloc.h>
  17. #include <string.h>
  18. #ifdef IBM_PC
  19. #include "stdlib.h"
  20. #else
  21. #endif
  22. #include "miscp.h"
  23. #include "adamrgp.h"
  24.  
  25.  
  26. #ifndef IBM_PC
  27. #include <sys/types.h>
  28. #include <sys/file.h>
  29. #endif
  30.  
  31. #ifdef SYSTEM_V
  32. #include <fcntl.h>
  33. #endif
  34. #ifndef IBM_PC
  35. #include <signal.h>
  36. #endif
  37.  
  38. #ifdef BSD
  39. #include "time.h"
  40. #include <sys/resource.h>
  41. #endif
  42.  
  43.  
  44. #ifdef IBM_PC
  45. #include "time.h"
  46. #else
  47. typedef long Time_type;
  48. #endif
  49.  
  50. /*
  51.  * Author: Alex Dreyzen Jan,1984
  52.  * Revised: Brian Siritzky, June 1984
  53.  * Revised: J. Chiabaut, November 1984
  54.  * Revised: D. Shields, May 1985
  55.  * Revised: D. Shields, July 1985
  56.  * Revised: G. Schenker, April 1986
  57.  * Revised: J. Chiabaut, May 1986
  58.  * Revised: D. Shields, July 1986
  59.  *    make into separate procedure, use single structure for all
  60.  *    messages, simplify logic
  61.  *           
  62.  */
  63.  
  64. /*
  65.  * This program takes two arguments giving the name of an adafile and 
  66.  * the msgfile/listfile  and then merges the messages in the file with 
  67.  * suffix '.msg' and source in file with suffix '.ada' to produce 
  68.  * listing file with suffix '.lis'.
  69.  *
  70.  * Function  main(argc,argv)  activates     functions   init_msg_map(),
  71.  * merge_ada_msg().
  72.  * Function init_msg_map()  counts  lines in the filename.msg,
  73.  * allocates space to store the keys and offsets of each  message,
  74.  * and sorts offsets in ascending order of the keys. Function
  75.  * printmsg() reads messages 
  76.  *
  77.  *
  78.  * Message format is:
  79.  *
  80.  * type_of_msg line_left col_left line_right col_right    <TAB>    message
  81.  *
  82.  * Where type_of_msg is one of :
  83.  *
  84.  *   PRAGMA_LIST_ON 1
  85.  *   PRAGMA_LIST_OFF 2
  86.  *   PRAGMA_LIST_ERR 3
  87.  *   PRAGMA_PAGE 4
  88.  *   ERR_LEXICAL 10
  89.  *   ERR_SYNTAX 11
  90.  *   ERR_SEMANTIC 12
  91.  *   ERR_WARNING 13
  92.  *   INFORMATION 14
  93.  *   ERR_BIND 15
  94.  *   ERR_COMPILER 16
  95.  *
  96.  *  Note that these are defined in config.h
  97.  */
  98.  
  99. #define MAXLINE 512
  100.  
  101. #define pagesize 55
  102.  
  103. #define VERSION_NO "1.11.1"
  104.  
  105. extern int  n_lex_err, n_syntax_err, n_semantic_err, n_binding_err, 
  106.             n_warning_err, n_generator_err, n_information;
  107. char    header[80];        /* header for output */
  108. int    pageno = 0;        /* output page number */
  109. int    realline = 0;        /* actual number of lines output */
  110. int    n_error = 0;        /* Number of errors */
  111. int    n_lex_err = 0;        /* Counts of the various kinds of messages */
  112. int    n_syntax_err = 0;
  113. int    n_semantic_err = 0;
  114. int    n_generator_err = 0;
  115. int    n_binding_err = 0;
  116. int    n_warning_err = 0;
  117. int     n_information = 0;
  118. /* Pointers to message, ada, and list files */
  119. FILE *msgfile, *adafile, *listfile;
  120. char   *pmsg,
  121.        *pada;
  122. int     line1,
  123.         line2,
  124.         col1,
  125.         col2,
  126.         error_type;
  127.  
  128. int    msgs_total,
  129.     m_type,
  130.     line_msg,
  131.     line_ada = 0,
  132.     list_on = 1,
  133.     msgs_read = 0;
  134. typedef struct Msg_ent {
  135.     short    msg_type;        /* message type */
  136.     short    msg_line1;        /* starting line */
  137.     short    msg_col1;        /* starting column */
  138.     short    msg_line2;        /* ending line */
  139.     short    msg_col2;        /* ending column */
  140.     short    msg_num;        /* message number (for stable sort) */
  141.     char        *msg_text;        /* message text */
  142.     struct    Msg_ent *msg_prev;    /* link to previous message */
  143. } Msg_ent;
  144. typedef struct Msg_ent *Msg;
  145. Msg *msg_array;
  146. char   *data, *line;
  147. int    adaeof = 0;
  148. char blankl[132] ;    /* blank line for underscore */
  149. char blanks[132];
  150. char dashl[132] ;    /* dash line for underscore */
  151. char dashes[132];
  152.  
  153. static void getada();
  154. static void getmsg();
  155. static void merge_ada_msg();
  156. static void pblank(int);
  157. static void underscore(int, int);
  158. static void printada();
  159. static void printmsg();
  160. static void newpage();
  161. static void newlin();
  162. static int init_msg_map(char *);
  163. static int compar(Msg *, Msg *);
  164. static char *sindex(char *, char);
  165. static int getlin();
  166. static char *msgtype(int);
  167.  
  168. int mrg(char *adafilename, char *msgfilename, char *listfilename,
  169.   char *list_arg)                                                    /*;mrg*/
  170. {
  171.     char   *s;
  172. #ifndef IBM_PC
  173.     Time_type bintim;
  174. #else
  175.     time_t bintim;
  176. #endif
  177.     char   *day, *month, *date, *clock, *year;
  178.     int list_opt;
  179.  
  180.     int    i,istatus;
  181.  
  182.     FILE *AVL_fp;
  183.  
  184.  
  185.     list_opt = strcmp(list_arg,"1") == 0;
  186.  
  187.     for (i=0;i<131;i++) blanks[i] = ' ';
  188.     for (i=0;i<131;i++) dashes[i] = '-';
  189.     blanks[131] = '\0';
  190.     dashes[131] = '\0';
  191.     data = malloc(MAXLINE);
  192.     line = data;
  193.  
  194.  
  195. /*
  196.  * if no adafile is given or not open, print only messages
  197.  */
  198.    adafile = efopen(adafilename, "r", "t");
  199. /*
  200.  * returns if the message file is empty and a listing is not required
  201.  */
  202.    istatus = init_msg_map(msgfilename);
  203. #ifdef DEBUG_MRG
  204.    printf("init_msg status %d\n",istatus);
  205. #endif
  206.    if (istatus==-1) return RC_INTERNAL_ERROR;
  207.    if(!istatus && !list_opt) return 0;
  208. #ifdef DEBUG_MRG
  209. printf("opening listfile %s\n",listfilename);
  210. #endif
  211.    listfile = efopen(listfilename, "w", "t");
  212.    if (listfile==(FILE *)0) {
  213.         fprintf(stderr, "Cannot open file %s.\n", listfilename);
  214.         listfile = stderr;
  215.    }
  216.  
  217. /* get the date and split it */
  218. #ifdef DEBUG_MRG
  219.     printf("get time\n");
  220. #endif
  221. /*  s = "Sun Apr 21 08:00:00 1985\n"; */
  222. #ifndef IBM_PC
  223.     bintim = time((long *) 0);
  224.     s = (char *) ctime(&bintim);
  225. #else
  226.     time(&bintim);
  227.     s = ctime(&bintim);
  228. #endif
  229.     day = s;
  230.     s += 3;
  231.     *s++ = '\0';
  232.     month = s;
  233.     s += 3;
  234.     *s++ = '\0';
  235.     date = s;
  236.     s += 2;
  237.     *s++ = '\0';
  238.     clock = s;
  239.     s += 8;
  240.     *s++ = '\0';
  241.     year = s;
  242.     s += 4;
  243.     *s = '\0';
  244.  
  245.     sprintf(header,
  246.         "NYU Ada/ED-C %s  %-15s  %s  %s %s %s  %s  PAGE   ",
  247.         VERSION_NO, OP_SYS, day, date, month, year, clock);
  248.     newpage();
  249. #ifdef DEBUG_MRG
  250. printf("post header\n");
  251. #endif
  252.     if (adafile!=(FILE *)0) {
  253.         getada();
  254.         realline++;
  255.     }
  256.     else {
  257.         line_ada = -1;
  258.         adaeof = EOF;
  259.         pada = (char *) 0;
  260.     }
  261.     getmsg();
  262.     if (pmsg == (char *) 0)
  263.         line_msg = 9999;
  264.     merge_ada_msg();
  265.     n_error = n_lex_err + n_syntax_err + n_semantic_err + n_binding_err
  266.       + n_generator_err;
  267.     if (n_error) {
  268. /*  AVL  */
  269.         AVL_fp = fopen("GWADA.SMM","w");
  270.         fprintf(AVL_fp, "%d %d %d %d %d %d total,Lex,syntax,semantic,bind,gen ",  n_error, n_lex_err, 
  271.             n_syntax_err, n_semantic_err, n_binding_err, n_generator_err);
  272.         fclose(AVL_fp);
  273.  
  274.         fprintf(listfile, "\n     %d error%s detected\n", n_error,
  275.           ((n_error == 1) ? "" : "s"));
  276.       /* print again to the terminal if it is not stderr */
  277.       if (listfile != stderr) {
  278.           fprintf(stderr,"%d error%s detected\n", n_error,
  279.                 ((n_error == 1) ? "" : "s"));
  280.       }
  281.  
  282.  
  283.     }
  284. /*    else {
  285.       fprintf(listfile, "\n    No errors detected\n");
  286.     }
  287. */
  288.     return 1;
  289. }
  290.  
  291. static void getada()                                    /*;getada */
  292. {
  293.     line_ada++;
  294.     adaeof = getlin();
  295.     if (adaeof != EOF)
  296.     pada = data;
  297.     else
  298.     pada = (char *) 0;
  299. }
  300.  
  301. static void getmsg()                                    /*;getmsg */
  302. {
  303.     Msg msgp;
  304.     if (msgs_read < msgs_total) {
  305.         msgp = msg_array[msgs_read];
  306. #ifdef DEBUG_MRG
  307.         printf("getmsg msgs_read %d msgp %p\n",msgs_read, msgp);
  308. #endif
  309.         pmsg = msgp -> msg_text;
  310.         line1 = msgp ->msg_line1;
  311.         line2 = msgp ->msg_line2;
  312.         line_msg = line2;
  313.         col1 = msgp -> msg_col1;
  314.         col2 = msgp -> msg_col2;
  315.         error_type = msgp -> msg_type ;
  316.         msgs_read++;
  317.         return;
  318.     }
  319.     else {
  320.         line_msg = 9999;
  321.         pmsg = (char *) 0;
  322.         return;
  323.     }
  324.  
  325. }
  326.  
  327. static void merge_ada_msg()                            /*;merge_ada_msg */
  328. {
  329.     int        dummsg;
  330.  
  331.     while((pmsg != (char *) 0) ||(pada != (char *) 0)) {
  332.         dummsg = 0;
  333.         if (line_msg < line_ada) {/* only if adafile is present */
  334.             while((line_msg < line_ada) && pmsg != (char *) 0) {
  335.                 printmsg();
  336.                 getmsg();
  337.             }
  338.         }
  339.  
  340.     if (line_msg == line_ada) {/* only if adafile is present */
  341.         switch(m_type) {
  342.         case PRAGMA_PAGE:
  343.             dummsg = 1;
  344.             if ((pada != (char *) 0)) {
  345.             if (list_on) {
  346.                 printada();
  347.             }
  348.             getada();
  349.             }
  350.             if (list_on)
  351.             newpage();
  352.             break;
  353.         case PRAGMA_LIST_OFF:
  354.             dummsg = 1;
  355.             if (adaeof != EOF) {
  356.             if (list_on)
  357.                 printada();
  358.             getada();
  359.             }
  360.             list_on = 0;
  361.             break;
  362.         case PRAGMA_LIST_ON:
  363.             dummsg = 1;
  364.             if (adaeof != EOF) {
  365.             printada();
  366.             getada();
  367.             }
  368.             list_on = 1;
  369.             break;
  370.         default:
  371.             dummsg = 0;
  372.             if (adaeof != EOF) {
  373.             printada();
  374.             getada();
  375.             }
  376.             printmsg();
  377.         }
  378.         getmsg();
  379.     }
  380.  
  381.     if (line_msg >= line_ada) {/* if only one message on line */
  382.         if (list_on) {
  383.             if (!dummsg)
  384.                 newlin();
  385.             while((line_msg > line_ada) && adaeof != EOF) {
  386.                    printada();
  387.                    getada();
  388.             }
  389.         }
  390.         else        /* read in lines, until the next message or EOF */
  391.             while((line_msg > line_ada) && adaeof != EOF)
  392.                 getada();
  393.  
  394.         if (adaeof == EOF) {/* adafile is not present or EOF reached */
  395.             while((pmsg != (char *) 0) &&(line_msg < 9999)) {
  396.                 printmsg();
  397.                 getmsg();
  398.             }
  399.             newlin();
  400.             while(pmsg != (char *) 0) {
  401.                 printmsg();
  402.                 getmsg();
  403.             }
  404.         }
  405.     }
  406.     }
  407. }
  408.  
  409. #define printhat(col)pblank(col-1);fprintf(listfile,"^");fprintf(listfile,"\n")
  410.  
  411. static void pblank(int col)                                        /*;pblank */
  412. {
  413.     strcpy(blankl,blanks);
  414.     realline++;
  415.     if (col > 0) {
  416.         blankl[col] = '\0';
  417.         fprintf(listfile, "%s", blankl);
  418.         blankl[col] = ' ';
  419.     }
  420. }
  421.  
  422. static void underscore(int col1, int col2)                    /*;underscore */
  423. {
  424.     strcpy(dashl,dashes);
  425.     pblank(col1 - 1);
  426.     fprintf(listfile, "<");
  427.     if (col2 - col1 > 1) {
  428.         dashl[col2 - col1 - 1] = '\0';
  429.         fprintf(listfile, "%s", dashl);
  430.         dashl[col2 - col1 - 1] = '-';
  431.     }
  432.     fprintf(listfile, ">");
  433.     fprintf(listfile, "\n");
  434. }
  435.  
  436. static void printada()                                        /*;printada */
  437. {
  438.     if (++realline >= pagesize)
  439.         newpage();
  440.     fprintf(listfile, "%4d:   %s", line_ada, pada);
  441. }
  442.  
  443. /*    This function prints error message, underscoring
  444.     the corresponding place in the source line        */
  445.  
  446. static void printmsg()                                        /*;printmsg */
  447. {
  448.     if (error_type >= ERR_LEXICAL) {
  449.         if (error_type < INFORMATION) {
  450.             if (adafile!=(FILE *)0)
  451.                 if (line1 == line2)
  452.                     if (col2 - col1 < 1) {
  453.                         printhat(col1 + 8);
  454.                     }
  455.                     else {
  456.                         underscore(col1 + 8, col2 + 8);
  457.                     }
  458.             else {
  459.                 fprintf(listfile,
  460.                   "\n       Between line %d column %d and line %d column %d\n",
  461.                   line1, col1, line2, col2);
  462.                 realline += 2;
  463.             }
  464.             else {
  465.                 realline += 2;
  466.                 if (line1 == line2)
  467.                     fprintf(listfile,
  468.                       "\n       Line %d between column %d and column %d\n",
  469.                       line1, col1, col2);
  470.                 else
  471.                     fprintf(listfile,
  472.                     "\n       Between line %d column %d and line %d column %d\n",
  473.                       line1, col1, line2, col2);
  474.             }
  475.         }
  476.     fprintf(listfile, "%s %s\n", msgtype(error_type), sindex(pmsg, '\t'));
  477.     if (realline++ >= pagesize)
  478.         newpage();
  479.     }
  480. }
  481.  
  482. static void newpage()                                    /*;newpage */
  483. {
  484.     /*
  485.      * this procedure outputs a form feed, resets the line counter
  486.      * and prints the standard header at the top of the page
  487.      */
  488.     pageno++;
  489.     realline = 1;
  490.     fprintf(listfile, "\f");
  491.     /* Add the page number to the end of the string */
  492.     fprintf(listfile, "%s %d\n\n", header, pageno);
  493. }
  494.  
  495. static void newlin()                                            /*;newlin */
  496. {
  497.     if ((++realline >= pagesize))
  498.     newpage();
  499.     else
  500.     fprintf(listfile, "\n");
  501. }
  502.  
  503. static int init_msg_map(char *msgfilename)                /*;init_msg_map */
  504. {
  505.     int    i, line1,line2,col1,col2,type;
  506.     int    nitems;
  507.     int    tab_found;
  508.     Msg    m_prev;
  509.     char *dp;
  510.     Msg        msg;
  511.  
  512.  
  513.     msgfile = efopen(msgfilename, "r","t");
  514.     if (msgfile==(FILE *)0) /* cannot open file */
  515.     return(FALSE);
  516.     m_prev = (Msg)0;
  517. #ifdef DEBUG_MRG
  518.     printf("start reading messages\n");
  519. #endif
  520.     while (fgets(data, MAXLINE, msgfile) != (char *)0) {
  521.         /* delete trailing newline */
  522.         data[strlen(data)-1] = '\0';
  523.         msg = (Msg) malloc(sizeof(Msg_ent));
  524.         if (msg==(Msg)0) {
  525.             fprintf(stderr,"Cannot read error messages\n");
  526.             return -1;
  527.         }
  528.         nitems = sscanf(data,"%d %d %d %d %d",
  529.           &type, &line1, &col1, &line2, &col2);
  530.         if (nitems!=5) {
  531.             printf("scanned %d\n",nitems);
  532.             printf(data,"%s\n");
  533.             chaos("bad message line");
  534.         }
  535.         msgs_total++;
  536.         msg->msg_num = msgs_total;
  537.         msg->msg_type = type;
  538.         msg->msg_line1 = line1;
  539.         msg->msg_col1 = col1;
  540.         msg->msg_line2 = line2;
  541.         msg->msg_col2 = col2;
  542.         msg->msg_prev = m_prev;
  543. #ifdef DEBUG_MRG
  544.         printf("new msg %p previous %p\n", msg, m_prev);
  545. #endif
  546.         m_prev = msg;
  547.         /* now find message text */
  548.         dp = data;
  549.         tab_found = 0;
  550.         while (*dp != '\0') {    /* skip to first tab */
  551.             if (*dp=='\t') {
  552.                 tab_found = 1;
  553.                 break;
  554.             }
  555.             dp++;
  556.         }
  557.         if (!tab_found) dp = data;
  558.         msg->msg_text = strjoin(dp,""); /* copy message text */
  559. #ifdef DEBUG_MRG
  560.         printf("mrg message %d type %d line1 %d col1 %d line2 %d col2 %d\n%s\n",
  561.          msg->msg_num, msg->msg_type, msg->msg_line1, msg->msg_col1,
  562.          msg->msg_line2, msg->msg_col2, msg->msg_text);
  563. #endif
  564.     }
  565.     /* now form msg_array, array of pointers to messages */
  566.     if (msgs_total) {
  567.         msg_array = (Msg *) calloc(msgs_total, sizeof(Msg));
  568.         if (msg_array == (Msg *)0) {
  569.         fprintf(stderr,"Cannot read error messages\n");
  570.         return -1;
  571.         }
  572.         for (i=msgs_total-1;i>=0;i--) {
  573.             msg_array[i] = m_prev;
  574. #ifdef DEBUG_MRG
  575.         printf("init msg_array i %d ptr %p m_prev %p\n",i,msg_array+i,m_prev);
  576. #endif
  577.         m_prev = m_prev->msg_prev;
  578. #ifdef DEBUG_MRG
  579.         printf("m_prev set to %p\n",m_prev);
  580. #endif
  581.         }
  582.     }
  583.     else {
  584.         msg_array = (Msg *) 0;
  585.     }
  586.  
  587.     if (msgs_total) {
  588.         qsort(msg_array, msgs_total, sizeof(Msg),
  589.           ( int (*)(const void *, const void *)) compar);
  590.     }
  591.     return msgs_total;
  592. }
  593.  
  594. static int  compar(Msg *a, Msg *b)                                /*;compar */
  595. {
  596.     Msg c,d;
  597.  
  598.     c = *a; d = *b;
  599.     /* compare by lines, then by columns */ 
  600.     if (c->msg_line2 >d->msg_line2) return 1;
  601.     else if (c->msg_line2 < d->msg_line2) return -1;
  602.     /* if same line, use message number */
  603.     else if (c->msg_num >d->msg_num) return 1;
  604.     else if (c->msg_num <d->msg_num) return -1;
  605.     return 0; /* if same */
  606. }
  607.  
  608. /* This is probably meant to be 4.2 index(), but give it separate name for now*/
  609. static char *sindex(char *s, char c)                        /*;sindex */
  610. {
  611.     while(*s != c) {
  612.         if ((*s == '\0') ||(*s == '\n'))
  613.             return s;
  614.         s++;
  615.     }
  616.     return++ s;
  617. }
  618.  
  619.  
  620. static int getlin()                                            /*;getlin */
  621. {
  622.     /* this is a stripped down version of getlin in adalex.c */
  623.     int        ch, ind = 0;
  624.  
  625.     if (feof(adafile))
  626.         return EOF;
  627.     for (;;) {
  628.         ch = getc(adafile);
  629.         if (ch == EOF)
  630.             break;
  631.         if (ch <= 13 && ch >= 10)
  632.             break;
  633.            if (ind == MAXLINE) {
  634.                while((ch = getc(adafile)) != EOF && !(10 <= ch && ch <= 13));
  635.                break;
  636.            }
  637.            else
  638.                data[ind++] = ch;
  639.     }
  640.  
  641.     data[ind++] = '\n';
  642.     data[ind] = '\0';
  643.     if (ch == EOF && !ind)
  644.         return EOF;
  645.     return (0);
  646. }
  647.  
  648. static char *msgtype(int n)        /*;msgtype */
  649. {
  650.     char   *s;
  651.  
  652.     switch(n) {
  653.     case ERR_LEXICAL:
  654.         s = "*** ERROR:";
  655.         n_lex_err++;
  656.         break;
  657.     case ERR_SYNTAX:
  658.         s = "*** ERROR:";
  659.         n_syntax_err++;
  660.         break;
  661.     case ERR_SEMANTIC:
  662.         s = "*** ERROR:";
  663.         n_semantic_err++;
  664.         break;
  665.     case ERR_COMPILER:
  666.         s = "*** ERROR:";
  667.         n_generator_err++;
  668.         break;
  669.     case ERR_WARNING:
  670.         s = "* WARNING:";
  671.         n_warning_err++;
  672.         break;
  673.     case INFORMATION:
  674.         s = "    ";
  675.             n_information++;
  676.         break;
  677.     case ERR_BIND:
  678.         s = "*** ERROR:";
  679.         n_binding_err++;
  680.         break;
  681.     }
  682.     return (s);
  683. }
  684.